package com.octopus.kernal.ui.element;

import java.lang.reflect.InvocationTargetException;
import java.util.List;
import java.util.Set;

import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlTransient;
import javax.xml.bind.annotation.XmlType;

import org.apache.commons.beanutils.BeanUtils;
import org.apache.commons.lang.StringUtils;
import org.springframework.context.MessageSource;
import org.springframework.context.i18n.LocaleContextHolder;

import com.octopus.kernal.model.BaseStruct;

@SuppressWarnings("serial")
@XmlType(name="SelectElement")
@XmlAccessorType(XmlAccessType.FIELD)
@XmlRootElement
public class SelectElement extends BaseElement{
	
	@XmlAttribute
	private String type = "String";
	
	@XmlAttribute
	private String labelProperty;
	
	@XmlAttribute
	private String cascade;
	
	@XmlAttribute
	private String onchange;
	
	@XmlAttribute
	private Boolean quickSelect = false;
	
	@XmlAttribute
	private Boolean autoFill = false;
	
	@XmlAttribute
	private String autoFillCascade;
	
	@XmlAttribute
	private String scope;
	
	@XmlTransient
	private List<Object> entitiesScrope;
	
	@XmlTransient
	private MessageSource messageSource;

	public MessageSource getMessageSource() {
		return messageSource;
	}

	public void setMessageSource(MessageSource messageSource) {
		this.messageSource = messageSource;
	}

	@SuppressWarnings("rawtypes")
	@Override
	public String toString(){
		StringBuffer str = new StringBuffer();
		StringBuffer strhidden = new StringBuffer();
		StringBuffer strbak = new StringBuffer();
		StringBuffer strAuto = new StringBuffer();
		if(this.isReadonly()){
			if(this.getValue() == null){
				return "";
			}else if(getValue() instanceof String || getValue() instanceof Integer || getValue() instanceof Long){
				if(StringUtils.isNotBlank(String.valueOf(getValue()))){
					String label = messageSource.getMessage("common.single.select." + getLabelProperty() + "." + getValue(), new Object[] { }, LocaleContextHolder.getLocale());
					str.append(label);
				}
			}else if(this.getValue() instanceof BaseStruct){
				str.append(null==labelProperty?"":getTranslationValue((String)((BaseStruct)this.getValue()).getAttributeValues().get(labelProperty)));
			}
		}else{
			str.append("<select ");
			strbak.append("<select ");
			strAuto.append("<input ");
			strhidden.append("<input type=\"hidden\" ");
			if(this.getId() != null){
				str.append("id=\"" + this.getId() + "\" ");
				strbak.append("id=\"" + this.getId() + "_bak\" ");
				strhidden.append("id=\"" + this.getId() + "\" ");
				strAuto.append("id=\"" + this.getId() + "_af\" ");
			}
			if(this.getName() != null){
				str.append("name=\"" + this.getName() + "\" ");
				strbak.append("name=\"" + this.getName() + "_bak\" ");
				strhidden.append("name=\"" + this.getName() + "\" ");
				strAuto.append("name=\"" + this.getName() + "_af\" ");
			}
			if(this.isDisabled())
				str.append("disabled=\"disabled\" ");
			if(StringUtils.isNotBlank(this.getStyle())){
				str.append("style=\"" + this.getStyle() + "\" ");
				String width = this.getStyle().substring(this.getStyle().indexOf("width:")+6, this.getStyle().indexOf("px"));
				strAuto.append("style=\"width:" + (Integer.valueOf(width)-18) + "px;position:absolute;left:-1000px;\" ");
			}
			strbak.append("style=\"display:none;\" ");
			if(StringUtils.isNotBlank(onchange)){
				if(!autoFill)
					str.append("onchange=\"" + onchange + "\" ");
				else
					str.append("onchange=\"" + onchange + ";onAutoFillValue('" + this.getId() + "')\" ");
			}else{
				if(autoFill)
					str.append("onchange=\"onAutoFillValue('" + this.getId() + "')\" ");
			}
			if(StringUtils.isBlank(autoFillCascade)){
				strAuto.append("onchange=\"onAutoFill('" + this.getId() + "')\"");
			}else{
				strAuto.append("onchange=\"onAutoFillCascade('" + this.getId() + "','" + autoFillCascade + "')\"");
			}
			str.append(">");
			strbak.append(">");
			if(getValue() instanceof BaseStruct){
				strhidden.append("value=\"" + ((BaseStruct)getValue()).getId() + "\" ");
			}else{
				strhidden.append("value=\"" + getValue() + "\" ");
			}
			str.append("<option></option>");
			strbak.append("<option></option>");
			if(entitiesScrope != null){
				for(Object entity : entitiesScrope){
					if(entity == null)
						continue;
					Object key = null;
					Object label = null;
					if(entity instanceof String){
						key = entity;
						label = messageSource.getMessage("common.single.select." + getLabelProperty() + "." + key, new Object[] { }, LocaleContextHolder.getLocale());
						str.append("<option value=\"" + key + "\" ");
						strbak.append("<option value=\"" + key + "\" ");
						if(this.getValue() != null && this.getValue().equals(key)){
							str.append("selected=\"selected\"");
							strbak.append("selected=\"selected\"");
							strAuto.append("value=\"" + label + "\"");
						}
						str.append(">" + label + "</option>");
						strbak.append(">" + label + "</option>");
					}else if(entity instanceof Integer || entity instanceof Long){
						key = entity;
						label = messageSource.getMessage("common.single.select." + getLabelProperty() + "." + key, new Object[] { }, LocaleContextHolder.getLocale());
						str.append("<option value=\"" + key + "\" ");
						strbak.append("<option value=\"" + key + "\" ");
						if(this.getValue() != null && this.getValue().equals(key)){
							str.append("selected=\"selected\" ");
							strbak.append("selected=\"selected\" ");
							strAuto.append("value=\"" + label + "\"");
						}
						str.append(">" + label + "</option>");
						strbak.append(">" + label + "</option>");
					}else if(entity instanceof BaseStruct){
						key = ((BaseStruct)entity).getId();
						Object labelobj = ((BaseStruct)entity).getAttributeValues().get(labelProperty);
						String labelstr = "";
						if(labelobj instanceof String){
							labelstr = (String)labelobj;
						}else if(labelobj instanceof Long){
							labelstr = String.valueOf(labelobj);
						}else if(labelobj instanceof BaseStruct){
							labelstr = (String)((BaseStruct)labelobj).getAttributeValues().get("name");
						}
						if(StringUtils.isNotBlank(cascade)){
							Object cas = ((BaseStruct)entity).getAttributeValues().get(cascade);
							if(cas == null){
								labelstr = getTranslationValue(labelstr);
							}else if(cas instanceof BaseStruct){
								labelstr = getTranslationValue(labelstr) + " [" + ((BaseStruct)cas).getId() + "] ";
							}else if(cas instanceof Integer){
								labelstr = getTranslationValue(labelstr) + " [" + ((Integer)cas + 1) + "] ";
							}else if(cas instanceof Long){
								labelstr = getTranslationValue(labelstr) + " [" + ((Long)cas + 1) + "] ";
							}
						}
						label = null==labelProperty?key:getTranslationValue(labelstr);
						str.append("<option value=\"" + key + "\" ");
						strbak.append("<option value=\"" + key + "\" ");
						BaseStruct value = null;
						Object obj = this.getValue();
						if(obj == null){
							
						}else if(obj instanceof BaseStruct){
							value = (BaseStruct)obj;
						}else if(obj instanceof Set){
							Object[] arr = ((Set)obj).toArray();
							if(arr != null && arr[0] != null)
								value = (BaseStruct)arr[0];
						}
						if(value != null && value.getId() != null && value.getId().equals(key)){
							str.append("selected=\"selected\" ");
							strbak.append("selected=\"selected\" ");
							if(label.toString().indexOf(" [") > 0)
								strAuto.append("value=\"" + label.toString().substring(0, label.toString().indexOf(" [")) + "\"");
							else
								strAuto.append("value=\"" + label + "\"");
						}
						str.append(">" + label + "</option>");
						strbak.append(">" + label + "</option>");
					}
				}
			}
			str.append("</select>");
			strbak.append("</select>");
			strhidden.append(">");
			strAuto.append(">");
			if(quickSelect){
				str.append("<a id=\"pick." + this.getId() + "\"" + (!this.isDisabled()?" href=\"javascript:pickSelected(document.getElementById('" + this.getId() + "'));\" ":" ") + ">");
				str.append("<img width=\"15\" height=\"15\" src=\"" + this.getRequest().getContextPath() + "/img/edit.png\">");
				str.append("</a>");
			}
			if(autoFill){
				str.append(strAuto.toString());
			}
			if(this.isDisabled() && this.getValue() != null){
				str.append(strhidden.toString());
			}
			if(StringUtils.isNotBlank(cascade)){
				str.append(strbak.toString());
			}
		}
		return str.toString();
	}
	
	public String getName() {
		if(super.getName() == null)
			return null;
		else if(type.equals("String"))
			return super.getName();
		else if(type.equals("Integer"))
			return super.getName();
		else if(type.equals("Boolean"))
			return super.getName();
		else if(type.equals("Date") || type.equals("Time"))
			return super.getName();
		else if(super.getName().lastIndexOf("Id") == (super.getName().length() - 2))
			return super.getName();
		else
			return super.getName() + "Id";
	}

	public List<Object> getEntitiesScrope() {
		return entitiesScrope;
	}

	public void setEntitiesScrope(List<Object> entitiesScrope) {
		this.entitiesScrope = entitiesScrope;
	}
	
	public SelectElement clone(){
		SelectElement result = new SelectElement();
		try {
			BeanUtils.copyProperties(result, this);
		} catch (IllegalAccessException e) {
			e.printStackTrace();
		} catch (InvocationTargetException e) {
			e.printStackTrace();
		}
		return result;
	}

	public String getType() {
		return type;
	}

	public void setType(String type) {
		this.type = type;
	}

	public String getLabelProperty() {
		return labelProperty;
	}

	public void setLabelProperty(String labelProperty) {
		this.labelProperty = labelProperty;
	}

	public String getCascade() {
		return cascade;
	}

	public void setCascade(String cascade) {
		this.cascade = cascade;
	}

	public String getOnchange() {
		return onchange;
	}

	public void setOnchange(String onchange) {
		this.onchange = onchange;
	}

	public Boolean getQuickSelect() {
		return quickSelect;
	}

	public void setQuickSelect(Boolean quickSelect) {
		this.quickSelect = quickSelect;
	}

	public String getScope() {
		return scope;
	}

	public void setScope(String scope) {
		this.scope = scope;
	}

	public Boolean getAutoFill() {
		return autoFill;
	}

	public void setAutoFill(Boolean autoFill) {
		this.autoFill = autoFill;
	}

	public String getAutoFillCascade() {
		return autoFillCascade;
	}

	public void setAutoFillCascade(String autoFillCascade) {
		this.autoFillCascade = autoFillCascade;
	}

}
